package socket;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * 聊天室客户端
 */
public class Client {
    /*
        java.net.Socket 套接字
        Socket封装了TCP协议的通讯细节,使用它可以与远端计算机建立连接
        并使用两个流(一个输入,一个输出)完成与远端计算机的数据交互.
     */
    private Socket socket;

    /**
     * 客户端构造方法,用于初始化客户端
     */
    public Client(){
        try {
            /*
                Socket常用构造方法:
                Socket(String host,int port)
                实例化Socket的过程就是与服务端建立连接的过程,如果
                指定的位置找不到服务端则会抛出异常!
                参数1:服务端的IP地址信息
                参数2:服务端开启的服务端口
                我们可以通过IP找到网络上服务端所在的计算机,通过端口
                可以连接到该计算机上的服务端应用程序.
             */
            System.out.println("正在连接服务端...");
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(
                            new FileInputStream("config.txt")
                    )
            );
            String host = br.readLine();
            int port = Integer.parseInt(br.readLine());
            socket = new Socket(host,port);
            System.out.println("与服务端建立连接!");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void start(){
        try {
            //启动读取服务端消息的线程
            ServerHandler handler = new ServerHandler();
            Thread t = new Thread(handler);
            t.start();

            /*
                Socket提供的方法:
                OutputStream getOutputStream()
                通过socket获取的输出流写出的字节会发送给链接的远端计算机
             */
            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osw
                    = new OutputStreamWriter(out,"UTF-8");
            BufferedWriter bw = new BufferedWriter(osw);
            PrintWriter pw = new PrintWriter(bw,true);

            Scanner scanner = new Scanner(System.in);
            while(true) {
                String line = scanner.nextLine();
                if("exit".equals(line)){
                    break;
                }
                pw.println(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                /*
                    当不再需要通讯时,应当调用socket的close方法.
                    该方法会给远端计算机发送一个断开连接的信号,然后
                    将连接关闭.
                 */
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }

    /**
     *  该线程用于循环读取服务端发送过来的消息
     */
    class ServerHandler implements Runnable{
        public void run(){
            try{
                InputStream in = socket.getInputStream();
                InputStreamReader isr
                        = new InputStreamReader(in,"UTF-8");
                BufferedReader br = new BufferedReader(isr);

                String line;
                while((line = br.readLine())!=null){
                    System.out.println(line);
                }

            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }

}
